package com.example.werewolf.service.impl.role;

import com.alibaba.fastjson2.JSONObject;
import com.example.werewolf.common.ActionType;
import com.example.werewolf.entity.Event;
import com.example.werewolf.entity.GamePhase;
import com.example.werewolf.entity.Player;
import com.example.werewolf.model.ActionSkill;
import com.example.werewolf.model.GameChatResp;
import com.example.werewolf.service.ActionStrategy;
import com.example.werewolf.utils.PrintUtils;
import com.example.werewolf.utils.RoleUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class WerewolfActionStrategy implements ActionStrategy {

    private static final int MAX_ROUNDS = 5; // 最多5轮讨论

    @Override
    public ActionSkill execute(List<Player> players, List<Player> actionPlayers,
                               GamePhase phase, List<Event> publicEvents, SseEmitter emitter) throws IOException {
        System.out.println("🐺 狼人行动阶段（" + actionPlayers.size() + "名狼人）开始，最多" + MAX_ROUNDS + "轮讨论...");

        List<Map<Integer, Integer>> roundVotes = new ArrayList<>(); // 每轮投票记录

        for (int round = 0; round < MAX_ROUNDS; round++) {
            Map<Integer, Integer> voteCount = new HashMap<>();

            List<Integer> duiyous = actionPlayers.stream().map(Player::getId).toList();
            for (Player player : actionPlayers) {
                // 每轮重新发送对话（依次）
                List<Event> personalEvents = player.getEvents();
                List<Event> globalEvents = new ArrayList<>();
                String chat = player.chat(buildWerewolfPrompt(duiyous, personalEvents, globalEvents));
                GameChatResp resp = parseResponse(chat);

                // 狼人发言记录
                PrintUtils.printPlayer(emitter, player, resp.getContent());

                for (Player player1 : actionPlayers) {
                    player1.saveMessage(Event.builder().affectedPlayer(duiyous).type("1")
                            .description(resp.getContent()).build());
                }

                if (resp != null && resp.getTargetNum() >= 0) {
                    voteCount.put(resp.getTargetNum(), voteCount.getOrDefault(resp.getTargetNum(), 0) + 1);
                }
            }

            roundVotes.add(voteCount); // 记录本轮投票

            // ✅ 判断是否达成一致：只有一个目标且所有狼人都选它
            if (voteCount.size() == 1) {
                Integer target = voteCount.keySet().iterator().next();
                long count = voteCount.values().stream().findFirst().orElse(0);
                if (count == actionPlayers.size()) {
                    System.out.println("✅ 狼人成功达成一致！目标：" + target + "（第" + (round + 1) + "轮）");

                    // 主持人处理行动
                    Player targetPlayer = RoleUtils.getTargetPlayer(players, target);
                    String acceptPlayer = "狼人";
                    String message = "【主持人 + 狼人】：狼队暗杀了" + targetPlayer.getId();
                    // 狼人刀人记录
                    PrintUtils.printSystem(emitter, message);

                    // 标记角色待刀
                    players.stream()
                            .filter(user -> user.getId() == target)
                            .findFirst()
                            .ifPresent(user -> user.setKilled(true));
                    return ActionSkill.builder()
                            .actionType(ActionType.WEREWOLF_KILL)
                            .werewolfTargetNum(target)
                            .build();
                }
            }

            System.out.println("🔄 第" + (round + 1) + "轮投票结果：" + voteCount);
        }

        // 如果超限仍未一致，取最高票（按规则，通常默认击杀最高票者）
        Integer target = findHighestVote(roundVotes);
        System.out.println("⚠️ 狼人未能完全一致，按最高票执行：" + target);

        // 主持人处理行动
        Player targetPlayer = RoleUtils.getTargetPlayer(players, target);
        String acceptPlayer = "狼人";
        String message = "【主持人 + 狼人】：狼队暗杀了" + targetPlayer.getId();
        // 狼人刀人记录
        PrintUtils.printSystem(emitter, message);

        // 标记角色待刀
        players.stream()
                .filter(user -> user.getId() == target)
                .findFirst()
                .ifPresent(user -> user.setKilled(true));

        return ActionSkill.builder()
                .actionType(ActionType.WEREWOLF_KILL)
                .werewolfTargetNum(target)
                .build();
    }

    private String buildWerewolfPrompt(List<Integer> duiyous, List<Event> privateEvents, List<Event> publicEvents) {
        StringBuilder werewolfPrompt = new StringBuilder("""
                行动核心逻辑：请与你的狼队友进行首夜发言讨论战术（此前你没有收到别人发言的记录）；并选择首夜刀人并安排后续战术，首夜必须刀人。
                """);
        werewolfPrompt.append("本局存活的狼队友是：").append(duiyous);
        werewolfPrompt.append("你所了解的私有信息:\n");
        for (Event privateEvent : privateEvents) {
            werewolfPrompt.append(privateEvent).append("\n");
        }

        werewolfPrompt.append("你所了解的公开信息:\n");
        for (Event publicEvent : publicEvents) {
            werewolfPrompt.append(publicEvent).append("\n");
        }
//        werewolfPrompt.append("""
//                请你根据狼人的身份，与队友商量战术并给出刀人选项，
//                并严格按照{"targetNum":xx, "content":"xxx对话内容"}回答对话，
//                不要返回其他参数，不要返回``` json ```，这会导致JSON序列化失败
//                """);
        return werewolfPrompt.toString();
    }

    private GameChatResp parseResponse(String json) {
        try {
            return JSONObject.parseObject(json, GameChatResp.class);
        } catch (Exception e) {
            System.err.println("解析狼人响应失败: " + e.getMessage());
            return null;
        }
    }

    private Integer findHighestVote(List<Map<Integer, Integer>> rounds) {
        Map<Integer, Integer> total = new HashMap<>();
        for (Map<Integer, Integer> round : rounds) {
            round.forEach((k, v) -> total.merge(k, v, Integer::sum));
        }
        return total.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(-1);
    }
}